<script lang="ts" setup>
import type { TreeNode } from '@vben/types';

import type { VbenFormProps, VxeGridProps } from '#/adapter';

import { nextTick, ref, watch } from 'vue';

import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';

import {
  DeleteOutlined,
  EditOutlined,
  KeyOutlined,
  LockOutlined,
  MoreOutlined,
  PlusCircleOutlined,
  SwapOutlined,
} from '@ant-design/icons-vue';
import {
  Button,
  Dropdown,
  Input,
  Menu,
  message,
  Modal,
  Popconfirm,
  Tree,
} from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter';
import {
  deleteDeptApi,
  deleteUserById,
  deleteUsersByDeptId,
  getDeptDetailApi,
  getDeptTreeApi,
  getUserRolesApi,
  getUsersApi,
  lockUserApi,
  resetUserPasswordApi,
  unlockUserApi,
} from '#/api/core/user';

import ChangePasswordModalComp from './change-password-modal.vue';
import DeptModalComp from './dept-modal.vue';
import TransferOrgModalComp from './transfer-org-modal.vue';
import NewUser from './user-drawer.vue';

// 引入国际化函数
import { $t } from '#/locales';

const [BaseDrawer, baseDrawerApi] = useVbenDrawer({
  connectedComponent: NewUser,
});

const [TransferOrgModal, transferOrgModalApi] = useVbenModal({
  connectedComponent: TransferOrgModalComp,
});

const [ChangePasswordModal, changePasswordModalApi] = useVbenModal({
  connectedComponent: ChangePasswordModalComp,
});

const [DeptModal, deptModalApi] = useVbenModal({
  connectedComponent: DeptModalComp,
});

const selectedDeptKey = ref<number | string>('1');

function openNewDrawer() {
  baseDrawerApi.setData({
    deptId: selectedDeptKey.value,
  });
  baseDrawerApi.open();
}

interface UserType {
  id: string;
  username: string;
  password: string;
  realName: string;
  email: string;
  telephone: string;
  attr: string;
  status: string;
  deptId: number;
  createTimeStr: string;
  updateTimeStr: string;
  lastLoginTimeStr: string;
}

const selectedRows = ref<UserType[]>([]);

// 左侧树节点(部门或用户组)的定义
const leftFormOptions: VbenFormProps = {
  schema: [],
};

// 1. 先定义 gridOptions
const gridOptions: VxeGridProps<UserType> = {
  checkboxConfig: {
    highlight: true,
    labelField: 'name',
    checkMethod: ({ row }) => row.attr === 'rw', // 复选框是否可选
  },
  columns: [
    { title: '', type: 'checkbox', width: 50 },
    { field: 'username', title: $t('user.columns.username'), align: 'left' },
    { field: 'realName', title: $t('user.columns.realName') },
    { field: 'status', title: $t('user.columns.status') },
    { field: 'email', title: $t('user.columns.email') },
    { field: 'phone', title: $t('user.columns.phone') },
    { field: 'createTimeStr', title: $t('user.columns.createTime') },
    { field: 'updateTimeStr', title: $t('user.columns.updateTime') },
    { field: 'lastLoginTimeStr', title: $t('user.columns.lastLoginTime') },
    {
      field: 'action',
      fixed: 'right',
      slots: { default: 'action' },
      title: $t('user.columns.action'),
      width: 140,
    },
  ],
  height: 'auto',
  keepSource: true,
  pagerConfig: {},
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues) => {
        const params = {
          page: page.currentPage,
          pageSize: page.pageSize,
          deptId: selectedDeptKey.value,
          ...formValues,
        };
        return await getUsersApi(params);
      },
    },
  },
};

// 2. 再定义 formOptions (不包含 handleSubmit)
const formOptions: VbenFormProps = {
  schema: [
    {
      component: 'Input',
      fieldName: 'username',
      label: $t('user.form.username'),
    },
    {
      component: 'Input',
      fieldName: 'realName',
      label: $t('user.form.realName'),
    },
    {
      component: 'Input',
      fieldName: 'email',
      label: $t('user.form.email'),
    },
    {
      component: 'Input',
      fieldName: 'phone',
      label: $t('user.form.phone'),
    },
  ],
};

// 添加一个变量存储当前的查询条件
const currentQueryParams = ref({});

// 3. 初始化 Grid 和 gridApi
const [Grid, gridApi] = useVbenVxeGrid({
  treeNodeOptions: leftFormOptions,
  formOptions,
  gridOptions,
});

// 4. 添加 formOptions 的 handleSubmit
formOptions.handleSubmit = async (values) => {
  currentQueryParams.value = values;
  gridApi.reload(values);
};

async function editUser(row: UserType) {
  try {
    const roles = await getUserRolesApi(row.id);
    baseDrawerApi.setData({
      ...row,
      roles: roles || [],
    });
    baseDrawerApi.open();
  } catch {
    message.error($t('user.getRolesFailed'));
  }
}

function handleSave() {
  gridApi.reload(); // 保存后刷新表格数据
}

function handleDeleteSelected() {
  if (selectedRows.value.length === 0) {
    return;
  }

  const ids = selectedRows.value.map((row) => row.id);

  Modal.confirm({
    title: $t('user.delete.title'),
    content: $t('user.delete.batchConfirm', { count: ids.length }),
    okText: $t('common.yes'),
    cancelText: $t('common.no'),
    async onOk() {
      await Promise.all(ids.map((id) => deleteUserById(id)));
      selectedRows.value = [];
      gridApi.reload();
    },
  });
}

const gridEvents = {
  checkboxChange({ records }: { records: UserType[] }) {
    selectedRows.value = records;
  },
  checkboxAll({ records }: { records: UserType[] }) {
    selectedRows.value = records;
  },
};

// 添加树相关的响应式数据
const treeData = ref<TreeNode[]>([]);
const filteredTreeData = ref<TreeNode[]>([]);
const expandedKeys = ref<(number | string)[]>([]);
const searchText = ref('');

// 添加一个函数来处理树节点据，确保包含 pid
function processTreeData(
  nodes: any[],
  parentId: null | number = null,
): TreeNode[] {
  return nodes.map((node) => ({
    key: node.id,
    title: node.title || node.name,
    pid: parentId,
    children: node.children
      ? processTreeData(node.children, Number(node.key))
      : undefined,
    ...node,
  }));
}

// 修改加载树数据的函数
async function loadDeptTree() {
  try {
    const data = await getDeptTreeApi();
    treeData.value = data ? processTreeData(data) : [];
    if (treeData.value.length > 0 && treeData.value[0]?.key) {
      expandedKeys.value = [treeData.value[0].key];
    }
  } catch {
    treeData.value = [];
    throw new Error('获取部门树失败');
  }
}

// 组件挂载时加载部门树
loadDeptTree();

// 过滤树节点的函数
function filterTreeNode(nodes: TreeNode[], keyword: string): TreeNode[] {
  return nodes
    .map((node) => {
      // 如果节点标题包含关键字，直接返回该节点及其所有子节点
      if (node.title.toLowerCase().includes(keyword.toLowerCase())) {
        return { ...node };
      }

      // 如果有子节点，递归过滤子节点
      if (node.children?.length) {
        const filteredChildren = filterTreeNode(node.children, keyword);
        // 如果过滤的子节点不为空，返回当前节点及过滤后的子节点
        if (filteredChildren.length > 0) {
          return {
            ...node,
            children: filteredChildren,
          };
        }
      }

      return null;
    })
    .filter((node): node is TreeNode => node !== null);
}

// 树搜索
function handleSearch(value = '') {
  const searchValue = value;
  searchText.value = searchValue;
  if (!searchValue.trim()) {
    filteredTreeData.value = treeData.value;
    return;
  }
  filteredTreeData.value = filterTreeNode(treeData.value, searchValue);
}

// 监听原始树数据化
watch(treeData, (newValue) => {
  filteredTreeData.value = newValue;
});

// 修改树节点选择处理函数
function handleTreeSelect(selectedKeys: (number | string)[], info: any) {
  // 如果是取消选择，则不更新 selectedDeptKey
  if (!info.selected) {
    return;
  }
  selectedDeptKey.value = selectedKeys[0] || '1';
  gridApi.reload(currentQueryParams.value);
}

// 展开全部
function expandAll() {
  const allKeys: (number | string)[] = [];
  const getKeys = (nodes: TreeNode[]) => {
    nodes.forEach((node) => {
      allKeys.push(node.key); // 不需要转换为字符串
      if (node.children?.length) {
        getKeys(node.children);
      }
    });
  };
  getKeys(treeData.value);
  expandedKeys.value = allKeys;
}

// 折叠全部
function collapseAll() {
  expandedKeys.value = [];
}

// 修改 handleAddDept 函数
async function handleAddDept(key: number | string) {
  const currentNode = findNodeInTree(treeData.value, key);
  if (currentNode) {
    deptModalApi.setData({
      isEdit: false,
      id: key,
      parentId: currentNode.pid,
      editData: null,
      rootNode: key === 0,
    });
    deptModalApi.setState({ title: $t('dept.title.add') });
    deptModalApi.open();
  }
}

// 添加一个辅助函数来在树中查找节点
function findNodeInTree(
  nodes: TreeNode[],
  key: number | string,
): null | TreeNode {
  for (const node of nodes) {
    if (node.key === key) {
      return node;
    }
    if (node.children?.length) {
      const found = findNodeInTree(node.children, key);
      if (found) return found;
    }
  }
  return null;
}

// 编辑部门函数
async function handleEditDept(key: number) {
  try {
    const deptData = await getDeptDetailApi(key);
    const editData = {
      id: deptData.id,
      name: deptData.name,
      description: deptData.description,
      pid: deptData.pid,
    };

    deptModalApi.setData({
      isEdit: true,
      parentId: deptData.pid,
      editData,
      rootNode: deptData.pid === 0,
    });
    deptModalApi.setState({ title: $t('dept.edit') });
    deptModalApi.open();
  } catch {
    throw new Error($t('dept.save.failed'));
  }
}

// 修改保存部门的处理函数
async function handleSaveDept() {
  await loadDeptTree();
  gridApi.reload(); // 刷新用户列表
}

// 修改删除部门的函数
async function handleDeleteDept(key: number) {
  try {
    // 先删除部门
    await deleteDeptApi(key);
    // 然后删除该部门下的所有用户
    await deleteUsersByDeptId(key);
    // 删除成功后新加载部门树和用户列表
    await loadDeptTree();
    gridApi.reload(); // 刷新用户列表
  } catch (error) {
    console.error('删除组织失败:', error);
  }
}

async function handleUnlock(row: UserType) {
  try {
    await unlockUserApi(row.id);
    message.success($t('user.unlock.success'));
    gridApi.reload();
  } catch {
    message.error($t('user.unlock.failed'));
  }
}

async function handleLock(row: UserType) {
  try {
    await lockUserApi(row.id);
    message.success($t('user.lock.success'));
    gridApi.reload();
  } catch {
    message.error($t('user.lock.failed'));
  }
}

function handleResetPassword(row: UserType) {
  try {
    resetUserPasswordApi(row.id);
    message.success($t('user.resetPassword.success'));
  } catch {
    message.error($t('user.resetPassword.failed'));
  }
  gridApi.reload();
}

function deleteUser(row: UserType) {
  deleteUserById(row.id); // 确认后执行删除操作
  gridApi.reload();
  message.success($t('common.action.deleteSuccess'));
}

// 密码修改处理函
function handleChangePassword(row: UserType) {
  changePasswordModalApi.setData({
    userId: row.id,
  });
  changePasswordModalApi.open();
}

// 添加处理移动的方法
const handleTransfer = async (record: UserType) => {
  transferOrgModalApi.setData({
    currentDeptId: String(record.deptId),
    userId: String(record.id),
  });
  // 先不显示模态框，等待数据加载完成
  await nextTick();
  transferOrgModalApi.open();
};
</script>

<template>
  <Page auto-content-height>
    <BaseDrawer :on-save="handleSave" />
    <Grid :grid-events="gridEvents" :tree-node-options="leftFormOptions">
      <!-- 添加左侧区域插槽 -->
      <template #left-area>
        <div class="flex h-full flex-col">
          <!-- 搜索框和更多按钮的容器 -->
          <div class="mb-2 flex items-center">
            <Input.Search
              v-model:value="searchText"
              :placeholder="$t('common.search')"
              allow-clear
              class="flex-1"
              @change="(e) => handleSearch(e.target.value)"
              @search="handleSearch"
            />
            <Dropdown>
              <Button class="ml-2">
                <MoreOutlined />
              </Button>
              <template #overlay>
                <Menu>
                  <Menu.Item @click="expandAll">
                    {{ $t('common.expandAll') }}
                  </Menu.Item>
                  <Menu.Item @click="collapseAll">
                    {{ $t('common.collapseAll') }}
                  </Menu.Item>
                </Menu>
              </template>
            </Dropdown>
          </div>

          <!-- 树组件 -->
          <div class="flex-1 overflow-auto">
            <Tree
              :expanded-keys="expandedKeys"
              :field-names="{
                title: 'title',
                key: 'key',
                children: 'children',
              }"
              :selected-keys="[selectedDeptKey]"
              :tree-data="filteredTreeData"
              @expand="(keys) => (expandedKeys = keys)"
              @select="handleTreeSelect"
            >
              <template #title="{ title, key }">
                <div
                  class="tree-node-wrapper"
                  @click="
                    () => console.log('Node key:', key, 'Type:', typeof key)
                  "
                >
                  <span>{{ title }}</span>
                  <div class="tree-node-actions">
                    <template v-if="String(key) === '1'">
                      <a class="action-link" @click.stop="handleAddDept(key)">
                        <PlusCircleOutlined class="action-icon" />
                      </a>
                    </template>

                    <template
                      v-else-if="String(key) !== '1' && String(key) !== '2'"
                    >
                      <a class="action-link" @click.stop="handleAddDept(key)">
                        <PlusCircleOutlined class="action-icon" />
                      </a>
                      <a class="action-link" @click.stop="handleEditDept(key)">
                        <EditOutlined class="action-icon" />
                      </a>
                      <Popconfirm
                        :title="$t('dept.delete.confirm')"
                        placement="bottomRight"
                        @click.stop
                        @confirm="handleDeleteDept(key)"
                      >
                        <a class="action-link">
                          <DeleteOutlined class="action-icon" />
                        </a>
                      </Popconfirm>
                    </template>
                  </div>
                </div>
              </template>
            </Tree>
          </div>
        </div>
      </template>

      <!-- 其他插槽持不变 -->
      <template #toolbar-actions>
        <Button class="mr-2" type="primary" @click="openNewDrawer">
          {{ $t('common.action.add') }}
        </Button>
        <Button
          v-if="selectedRows.length > 0"
          class="ml-2"
          danger
          type="primary"
          @click="handleDeleteSelected"
        >
          {{ $t('common.action.delete') }}
        </Button>
      </template>

      <template #action="{ row }">
        <Button class="px-1" type="link" @click="() => handleUnlock(row)">
          {{ $t('user.unlock.title') }}
        </Button>
        <template v-if="row.attr !== 'r'">
          <Button class="px-1" type="link" @click="() => editUser(row)">
            {{ $t('common.action.edit') }}
          </Button>
        </template>
        <Dropdown v-model:visible="row.dropdownVisible" :trigger="['click']">
          <Button class="px-1" type="link">
            <MoreOutlined />
          </Button>
          <template #overlay>
            <Menu>
              <Menu.Item>
                <Popconfirm
                  :arrow-point-at-center="true"
                  :overlay-style="{ padding: '0 24px' }"
                  :title="$t('user.resetPassword.confirm')"
                  placement="left"
                  @cancel="() => {}"
                  @click.stop
                  @confirm="
                    async () => {
                      await handleResetPassword(row);
                      row.dropdownVisible = false;
                    }
                  "
                >
                  <div @click.stop>
                    <KeyOutlined /> {{ $t('user.resetPassword.title') }}
                  </div>
                </Popconfirm>
              </Menu.Item>
              <Menu.Item @click="() => handleChangePassword(row)">
                <EditOutlined /> {{ $t('user.changePassword.title') }}
              </Menu.Item>
              <template v-if="row.attr !== 'r'">
                <Menu.Item @click="() => handleLock(row)">
                  <LockOutlined /> {{ $t('common.lock') }}
                </Menu.Item>
                <Menu.Item @click="() => handleTransfer(row)">
                  <SwapOutlined /> {{ $t('user.transfer.title') }}
                </Menu.Item>
                <Menu.Divider />
                <Menu.Item>
                  <Popconfirm
                    :arrow-point-at-center="true"
                    :overlay-style="{ padding: '0 24px' }"
                    :title="$t('user.delete.confirm')"
                    placement="left"
                    @cancel="() => {}"
                    @click.stop
                    @confirm="
                      async () => {
                        await deleteUser(row);
                      }
                    "
                  >
                    <div class="text-red-500" @click.stop>
                      <DeleteOutlined /> {{ $t('common.action.delete') }}
                    </div>
                  </Popconfirm>
                </Menu.Item>
              </template>
            </Menu>
          </template>
        </Dropdown>
      </template>
    </Grid>

    <!-- Department Modal -->
    <DeptModal @save="handleSaveDept" />

    <!-- Change Password Modal -->
    <ChangePasswordModal />

    <!-- Transfer Organization Modal -->
    <TransferOrgModal />
  </Page>
</template>

<style scoped>
.tree-node-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  padding-right: 8px;
}

:deep(.ant-tree-node-content-wrapper) {
  width: 100%;
}

:deep(.ant-tree-node-selected) {
  width: 100%;
}

.tree-node-actions {
  position: absolute;
  right: 0;
  z-index: 1;
  display: none;
  align-items: center;
  height: 100%;
  white-space: nowrap;
  background: transparent;
}

.tree-node-wrapper:hover .tree-node-actions {
  display: flex;
  gap: 4px;
  padding-right: 16px;
  padding-left: 8px;
  background: transparent;
}

/* 操作链接样式 */
.action-link {
  display: flex;
  align-items: center;
  padding: 4px;
  color: rgb(0 0 0 / 45%);
  background: transparent;
  transition: color 0.3s;
}

.action-link:hover {
  color: #1890ff;
  background: transparent;
}

.action-icon {
  font-size: 14px;
}

/* 防止节点文字与钮重叠 */
.tree-node-wrapper > span {
  padding-right: 90px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
</style>
